#include "Sink.h"
// --------------------------------------------------------------
Sink_ToFile::Sink_ToFile(const string FileName, const double it_end,const double idt,const int imode){
#ifdef DEBUG
  cout << "Sink_ToFile::Sink_ToFile()\n";
#endif
  dt   = idt;
  int Dim_Input[1] = {1};
  int Dim_Output[1] = {0};
  block::initialize(1,Dim_Input,0,Dim_Output,dt);

  int i;
  t_end = it_end;
  mode = imode;
  string FileName_avg = FileName+".dat";

  fout_avg.open(FileName_avg.c_str());
  if(mode == 1){
    string FileName_detail = FileName+"_detail.dat";
    fout_detail.open(FileName_detail.c_str());
  }

  t_node = int(t_end/idt)+1;
  for(i = 0;i<t_node;++i){
    time.push_back(i*dt);
    value.push_back(0.0);
    value2.push_back(0.0);
  }
  t_idx = 0;

  repeated = 0;
#ifdef DEBUG
  cout << "END Sink_ToFile::Sink_ToFile()\n";
#endif
}
// --------------------------------------------------------------
Sink_ToFile::~Sink_ToFile()
{
#ifdef DEBUG
  cout << "Sink_ToFile::~Sink_ToFile()\n";
#endif
  int i;

  if(mode == 1){
    fout_detail.close();
  }
  double mean;
  double var;

  // repeated = 0: no call to reset(), only one run
  // repeated > 0: Call reset(), multiple runs
  if(repeated == 0)
    repeated++;

  for(i=0;i<t_node;++i){
    mean = value[i]/repeated;
    var  = value2[i]/repeated-mean*mean;
    if(var < 1e-15 && var > -1e-15)
      var = 0.0;
    fout_avg << setw(COLUMNWIDTH) << fixed << setprecision(3) << time[i] 
	     << setw(COLUMNWIDTH) << scientific << setprecision(6) << mean 
	     << setw(COLUMNWIDTH) << scientific << setprecision(6) << var;
    if(i!=t_node-1){fout_avg << "\n";}
  }
  fout_avg.close();

  if(mode == 1){
    fout_detail.close();
  }
#ifdef DEBUG
  cout << "END Sink_ToFile::~Sink_ToFile()\n";
#endif
}
// --------------------------------------------------------------
void Sink_ToFile::update(const double itime, const double ivalue){
  if(itime>t_end){
    return;
  }
  while(time[t_idx]<=itime+0.01*dt){
    value[t_idx] = value[t_idx]+ivalue;
    value2[t_idx]= value2[t_idx]+ivalue*ivalue;
    if(mode == 1){	
      fout_detail << setw(COLUMNWIDTH) << fixed << setprecision(3) << itime 
		  << setw(COLUMNWIDTH) << scientific << setprecision(6) << ivalue
	          << "\n";
    }
    t_idx++;
    if(t_idx == t_node)
      break;
  }
  return;

}
// --------------------------------------------------------------
void Sink_ToFile::update(double sysTime){
  if(block::inputs[0]!=NULL){
    update(sysTime,inputs[0][0]);
  }
  return;
}
// --------------------------------------------------------------
void Sink_ToFile::reset()
{
  t_idx = 0;
  repeated++;
}
// --------------------------------------------------------------
Sink_ToFile_vector::Sink_ToFile_vector(const std::string iFileName, const double idt, const int iInputDim){
  int output_dim[1] = {0};
  int input_dim[1];
  input_dim[0] = iInputDim;
  block::initialize(1,input_dim,0,output_dim,idt);
  FileName = iFileName+".dat";
  fout.open(FileName.c_str());
}
// --------------------------------------------------------------
Sink_ToFile_vector::~Sink_ToFile_vector(){
  fout.close();
}
// --------------------------------------------------------------
void Sink_ToFile_vector::update(const double sysTime){
  int i;
  while(time<=sysTime)
  {
    fout << setw(COLUMNWIDTH) << time;
    for(i=0;i<input_dim[0];i++)
    {
      fout << setw(COLUMNWIDTH) << inputs[0][i];
    }
    fout << "\n";
    time += dt;
  }
}
// --------------------------------------------------------------


